/*
 * Copyright (c) 2011 Ball State University
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * NOTE:
 * Derivative work based on the Google IO 2011 Schedule app released for open source
 * http://code.google.com/p/iosched/
 */

package edu.bsu.android.gtv.apps.bconnected.ui;

import java.util.ArrayList;

import edu.bsu.android.gtv.apps.bconnected.data.ConnectionData;
import edu.bsu.android.gtv.apps.bconnected.R;
import edu.bsu.android.gtv.apps.bconnected.data.CourseData;
import edu.bsu.android.gtv.apps.bconnected.data.PersonData;
import edu.bsu.android.gtv.apps.bconnected.objects.Course;
import edu.bsu.android.gtv.apps.bconnected.objects.Person;
import edu.bsu.android.gtv.apps.bconnected.ui.HomeActivity;
import edu.bsu.android.gtv.apps.bconnected.ui.base.BaseActivity;
import edu.bsu.android.gtv.apps.bconnected.util.Adapters;
import edu.bsu.android.gtv.apps.bconnected.util.AnalyticsUtils;
import edu.bsu.android.gtv.apps.bconnected.util.Constants;
import edu.bsu.android.gtv.apps.bconnected.util.FractionalTouchDelegate;
import edu.bsu.android.gtv.apps.bconnected.util.LoginHelper;
import edu.bsu.android.gtv.apps.bconnected.util.UIUtils;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.RectF;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.LinearLayout;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CompoundButton.OnCheckedChangeListener;

/**
 * An activity that shows detail information for a classmate, including shared coures. Activity that is started when a user selects a 
 * classmate from the list on the {@link CourseInfoActivity}.
 * @author Kyle Parker, University Computing Services
 */
public class ClassmateInfoActivity extends BaseActivity {
    private static final String TAG = "ClassmateInfoActivity";
    private static final String TAG_SHARED_COURSES = "shared"; 

    private TabHost mTabHost;
    private View mLoadingSpinner;
    private View mSharedCoursesSpinner;
    private Activity mActivity;
    private BroadcastReceiver mReceiver;
    private CompoundButton mStarred;
    
    private String mLoginGuid;
    private String mBSUID;
    private String mPersonBSUID;
    private Person mPerson;
    private String mTermNumber;
    private String mTermYear;
    private String mTermID;
    private boolean mLogin;
    
    private int mPersonPosition = 0;
    private int mCoursePosition = 0;
    private int mTermPosition = 0;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_classmate_info);
		
        getActivityHelper().setupActionBar(false, "Course Schedule | Classmate");        
        mActivity = this;
        
        handleLogout();    
        handleLogin();
                
        mTabHost = (TabHost) findViewById(android.R.id.tabhost);
       	mTabHost.setup();

        mLoadingSpinner = findViewById(R.id.loading_spinner); 
        mLoadingSpinner.setVisibility(View.VISIBLE);	
        
        mSharedCoursesSpinner = findViewById(R.id.spinner_shared_courses); 
        mSharedCoursesSpinner.setVisibility(View.VISIBLE);	
        
        mStarred = (CompoundButton) findViewById(R.id.star_button);
        mStarred.setFocusable(true);
        mStarred.setClickable(true);
        
        // Larger target triggers star toggle
        final View starParent = findViewById(R.id.name);
        FractionalTouchDelegate.setupDelegate(starParent, mStarred, new RectF(0.6f, 0f, 1f, 0.8f));
    	
        setupSharedCoursesTab();
        getExtras();
		
		// Hide the classmate while the data is loading
		hideClassmate();		
		if (mLogin) {
			loadClassmate();
		}

        AnalyticsUtils.getInstance(mActivity).trackPageView("/Classmate");
    }
    
    @Override 
    public void onDestroy() {
    	super.onResume();
    	mActivity.unregisterReceiver(mReceiver);
    }
    
    /**
     * Get the extras from the Intent
     */
    public void getExtras() {
		Bundle extras = getIntent().getExtras(); 

		if (extras != null) {
			if (extras.getString(Constants.EXTRA_CLASSMATE_POSITION) != null) {
				mPersonPosition = Integer.parseInt(extras.getString(Constants.EXTRA_CLASSMATE_POSITION));
			}
			if (extras.getString(Constants.EXTRA_COURSE_POSITION) != null) {
				mCoursePosition = Integer.parseInt(extras.getString(Constants.EXTRA_COURSE_POSITION));
			}
			if (extras.getString(Constants.EXTRA_TERM_POSITION) != null) {
				mTermPosition = Integer.parseInt(extras.getString(Constants.EXTRA_TERM_POSITION));
			}
			if (extras.getString(Constants.EXTRA_TERM_ID) != null) {
				mTermID = extras.getString(Constants.EXTRA_TERM_ID);
			}
		}
    }

    /**
     * Using a new thread, separate from the main activity, load the classmate information from the service handler
     */
    private void loadClassmate() {		
        Runnable load = new Runnable(){
            public void run() {
            	try {
            		if (CourseData.getCourseCount() > 0) {
	        	    	// There will only be 1 course in the array based on the web service query (crn and termID), so get the information from the first position
	        	        String crn = CourseData.getCourse(mCoursePosition).getCourseRefNum();
	        	        mTermNumber = CourseData.getCourse(mCoursePosition).getTermNumber();
	        	        mTermYear = CourseData.getCourse(mCoursePosition).getTermYear();
	        	        
	        	    	// Display the course information including campus map clickable image (launch map intent), classmates and instructors
	        	        // NOTE: This was not needed - retrieve the entire class list and then select the position based on the item click event
	        	        PersonData.initializeClassmate(mBSUID, crn, mTermNumber, mTermYear, mLoginGuid, mActivity);
	
	                    if (PersonData.getClassmateCount() > 0) {
		                	// Retrieve the classmate information based on the position in the list
		                	mPerson = PersonData.getClassmate(mPersonPosition);		
		                	mPersonBSUID = mPerson.getBSUID();
	                    }
                	}
        	    	
            		mActivity.runOnUiThread(returnClassmate);
            	} catch (Exception ex) {
                    AnalyticsUtils.getInstance(mActivity).trackPageView(TAG + ": " + ex.getMessage());
            	}
            }
        };
        
        Thread thread = new Thread(null, load, "loadClassmate");
        thread.start();
    }
    
    /**
     * Display the classmate info in a separate thread and when completed, set the visibility of the spinner to "gone"
     */
    private Runnable returnClassmate = new Runnable(){
        public void run() {
        	// If the call to the classmate service did not return the "error" attribute, then display the classmates, otherwise 
        	// the expiration date has expired for the user or they are not authorized under the current credentials to access the information.
        	// When retrieving data from the .NET service handler, the BSU ID and login guid are matched against the SQL Server database.  If
        	// the combination of the two do not match, then the user is not permitted to retrieve the requested data.  The guards against
        	// someone hacking the querystring parameters to retrieve the information of another student.
        	if (PersonData.getClassmateAuth()) {
        		displayClassmate();
        	} else {
                findViewById(R.id.empty_classmate_info_container).setVisibility(View.VISIBLE);
                ((TextView) findViewById(R.id.empty_classmate_info)).setText(R.string.error_auth);
        	}
        	
            mLoadingSpinner.setVisibility(View.GONE);
        }
    };

    /**
     * Using a new thread, separate from the main activity, load the shared courses from the service handler
     */
    private void loadSharedCourse() {			
        Runnable load = new Runnable(){
            public void run() { 
            	try {
            		CourseData.initializeSharedCourses(mBSUID, mPersonBSUID, mTermNumber, mTermYear, mLoginGuid, mActivity);
        	    	
            		mActivity.runOnUiThread(returnSharedCourse);
            	} catch (Exception ex) {
                    AnalyticsUtils.getInstance(mActivity).trackPageView(TAG + ": " + ex.getMessage());
            	}
            }
        };
        
        Thread thread = new Thread(null, load, "loadSharedCourse");
        thread.start();
    }
    
    /**
     * Display the shared courses in a separate thread
     */
    private Runnable returnSharedCourse = new Runnable(){
        public void run() {
        	// If the call to the shared courses service did not return the "error" attribute, then display the shared courses, otherwise 
        	// the expiration date has expired for the user or they are not authorized under the current credentials to access the information.
        	// When retrieving data from the .NET service handler, the BSU ID and login guid are matched against the SQL Server database.  If
        	// the combination of the two do not match, then the user is not permitted to retrieve the requested data.  The guards against
        	// someone hacking the querystring parameters to retrieve the information of another student.
        	if (CourseData.getSharedCourseAuth()) {
                displaySharedCourses(CourseData.getSharedCourses());
                
                if (CourseData.getSharedCoursesCount() == 0) {
                    TextView empty = ((TextView) findViewById(R.id.empty_shared_courses));
                    empty.setVisibility(View.VISIBLE);
                }
        	} else {
                findViewById(R.id.classmate_info_container).setVisibility(View.VISIBLE);
                TextView empty = ((TextView) findViewById(R.id.empty_shared_courses));
                empty.setVisibility(View.VISIBLE);
                empty.setText(R.string.error_auth);
        	}
        	        	
            mSharedCoursesSpinner.setVisibility(View.GONE);
        }
    };
    
    /**
     * Display the classmate information, set the starred status and show the shared courses
     */
    private void displayClassmate() {
    	if (mPerson != null) { 	
    		LinearLayout view = (LinearLayout) findViewById(R.id.classmate_info_container);
            view.setVisibility(View.VISIBLE);
        	view.setBackgroundResource(R.color.content_background);
            
            loadSharedCourse();
            
        	// Set up the contact values - these will be used for the "add to contacts" intent for the options menu
    		String name = (mPerson.getFirstName() + " " + mPerson.getLastName() + " " + mPerson.getNameSuffix()).trim();
    		String address = "";
        		
    		UIUtils.displayTextView(view, R.id.name, name);
    		UIUtils.displayTextView(view, R.id.email, mPerson.getEmailAddress());
    		UIUtils.displayTextView(view, R.id.phone, mPerson.getPhone());
    		UIUtils.displayTextView(view, R.id.address, address);
	        
            // Unregister around setting checked state to avoid triggering listener since change isn't user generated.
            mStarred.setOnCheckedChangeListener(null);
            mStarred.setChecked(mPerson.getStarred());
            mStarred.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
			    	ConnectionData.insertConnection(mBSUID, mLoginGuid, mPersonBSUID, Constants.VALUE_PERSON_TYPE_STUDENT, isChecked, mActivity);
			    }           	
            });
    	} else { 
    		hideClassmate();
    		((TextView) showEmptyClassmate().findViewById(R.id.empty_classmate_info)).setText(R.string.empty_classmate_info);
    	}
    }

    /**
     * Hide the classmate view during the load process or if the classmate object is empty
     */
	private void hideClassmate() { 
		LinearLayout view = (LinearLayout) findViewById(R.id.classmate_info_container);
        view.setVisibility(View.GONE);			
	}

    /**
     * Show the empty classmate view during the load process or if the classmate object is empty
     */
	private View showEmptyClassmate() {
		LinearLayout view = (LinearLayout) findViewById(R.id.empty_classmate_info_container);
		view.setVisibility(View.VISIBLE);
        view.setBackgroundResource(R.drawable.empty_schedule);
        
        return view;
	}
    
    /**
     * Display the shared courses for the student and the classmate
     * @param ArrayList<Course> sharedCourses
     */
    private void displaySharedCourses(ArrayList<Course> sharedCourses) {
    	Adapters.CourseAdapter adapter = new Adapters.CourseAdapter(mActivity, sharedCourses, Constants.TARGET_SHARED_COURSE);

        final ListView lv = ((ListView) findViewById(R.id.shared_courses));
        lv.setAdapter(adapter);  
        lv.setOnItemClickListener(new OnItemClickListener(){
			public void onItemClick(AdapterView<?> parentView, View childView, int position, long id) {
		        final Intent intent = new Intent(Intent.ACTION_VIEW, null, mActivity, CourseInfoActivity.class);

		        // In order to get the correct course on the course info activity, get the CRN at the position specified 
		        // and return as an extra in the intent
		        Course course = (Course) lv.getItemAtPosition(position);
		        
		        intent.putExtra(Constants.EXTRA_CLASSMATE_POSITION, Integer.toString(position));
		        intent.putExtra(Constants.EXTRA_COURSE_REF_NUM, course.getCourseRefNum());
		        intent.putExtra(Constants.EXTRA_COURSE_POSITION, Integer.toString(mCoursePosition));
		        intent.putExtra(Constants.EXTRA_TERM_POSITION, Integer.toString(mTermPosition));
		        intent.putExtra(Constants.EXTRA_TERM_ID, mTermID);
		        
		        mActivity.startActivity(intent);
			}
		});
    }
    
    /**
     * Build and add "shared courses" tab.
     */
    private void setupSharedCoursesTab() {
        // Summary content comes from existing layout
        mTabHost.addTab(mTabHost.newTabSpec(TAG_SHARED_COURSES)
                .setIndicator(UIUtils.buildIndicator(R.string.tab_classmate_shared_courses, mActivity))
                .setContent(R.id.tab_shared_course));
    }

    /**
     * In order to protect the activity from the back stack after a student logs out, remove the activity 
     * If the student hits the back button, this will take them to the Home activity
     */
    private void handleLogout() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Constants.ACTION_LOGOUT);
        mReceiver = new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
		        intent = new Intent(Intent.ACTION_VIEW, null, mActivity, HomeActivity.class);
		        intent.putExtra(Constants.EXTRA_LOGIN_STATUS, Integer.toString(Constants.LOGIN_STATUS_LOGOUT));
		        
		        mActivity.startActivity(intent); 
			    mActivity.finish();
			}
		};
		
        mActivity.registerReceiver(mReceiver, intentFilter);
    }
    
    /**
     * Determine if the person has logged in and whether there is a person object in the database
     * Get the student's BSU ID for use throughout the application
     */
    private void handleLogin() {
    	Person person = LoginHelper.checkLogin(mActivity);
    	
    	if (person != null) {
    		mBSUID = person.getBSUID();
        	mLoginGuid = person.getLoginGuid();
        	
        	mLogin = true;
    	} else {
	        Intent intent = new Intent(Intent.ACTION_VIEW, null, mActivity, HomeActivity.class);
	        intent.putExtra(Constants.EXTRA_LOGIN_STATUS, Integer.toString(Constants.LOGIN_STATUS_NOT_LOGGED_IN));
	        
	        mActivity.startActivity(intent); 
		    mActivity.finish();
		    
		    mLogin = false;
    	}    	
    }
}
